package com.leyou.item.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.leyou.common.constants.MQConstants;
import com.leyou.common.exception.ExceptionEnum;
import com.leyou.common.exception.LyException;
import com.leyou.common.utils.BeanHelper;
import com.leyou.common.vo.PageResult;
import com.leyou.item.domain.Sku;
import com.leyou.item.domain.Spu;
import com.leyou.item.domain.SpuDetail;
import com.leyou.item.dto.*;
import com.leyou.item.mapper.SkuMapper;
import com.leyou.item.mapper.SpuDetailMapper;
import com.leyou.item.mapper.SpuMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Transactional
public class GoodsService {
    @Autowired
    private SpuMapper spuMapper;
    @Autowired
    private SpuDetailMapper spuDetailMapper;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private BrandService brandService;
    @Autowired
    private SkuMapper skuMapper;
    @Autowired
    private AmqpTemplate amqpTemplate;

    /**
     * 查询商品列表信息
     *
     * @param page
     * @param rows
     * @param key
     * @param saleable
     * @return
     */
    public PageResult<SpuDTO> spuPageQuery(Integer page, Integer rows, String key, Boolean saleable) {
        //设置分页参数
        PageHelper.startPage(page, rows);
        //得到封装参数对象
        Example example = new Example(Spu.class);
        Example.Criteria criteria = example.createCriteria();
        if (StringUtils.isNoneBlank(key)) {
            criteria.andLike("name", "%" + key + "%");
        }
        if (saleable != null) {
            criteria.andEqualTo("saleable", saleable);
        }
        //查询数据库
        List<Spu> spus = spuMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(spus)) {
            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }
        //得到分页对象
        PageInfo<Spu> spuPageInfo = new PageInfo<>(spus);
        List<Spu> list = spuPageInfo.getList();
        //得到spudto的集合
        List<SpuDTO> spuDTOS = BeanHelper.copyWithCollection(list, SpuDTO.class);
        //给集合中的brandName和categoryName赋值
        handlerBrandNameAndCategoryName(spuDTOS);
        PageResult<SpuDTO> pageResult = new PageResult<>(spuPageInfo.getTotal(), spuPageInfo.getPages(), spuDTOS);
        return pageResult;
    }

    private void handlerBrandNameAndCategoryName(List<SpuDTO> spuDTOS) {
        spuDTOS.forEach(spuDTO -> {//遍历spuDTOS集合得到spuDTO对象
            String categoryNames = categoryService.findCategoryByIds(spuDTO.getCategoryIds())//得到分类集合
                    .stream()//将分类转成流
                    .map(CategoryDTO::getName)//开始收集name
                    .collect(Collectors.joining("/"));//收集成以/分割的字符串
            spuDTO.setCategoryName(categoryNames);

            BrandDTO brandDTO = brandService.findBrandById(spuDTO.getBrandId());
            spuDTO.setBrandName(brandDTO.getName());
        });
    }

    /**
     * 新增商品
     *
     * @param spuDTO
     */
    public void saveGoods(SpuDTO spuDTO) {
        try {
            //保存spu将dto对象转换为pojo
            Spu spu = BeanHelper.copyProperties(spuDTO, Spu.class);
            //指定新保存商品是下架
            spu.setSaleable(false);
            //保存操作
            spuMapper.insert(spu);

            //保存spuDetail
            SpuDetailDTO spuDetailDTO = spuDTO.getSpuDetail();
            SpuDetail spuDetail = BeanHelper.copyProperties(spuDetailDTO, SpuDetail.class);
            //设置外键
            spuDetail.setSpuId(spu.getId());
            spuDetailMapper.insert(spuDetail);

            //保存sku集合
            //给sku集合中的对象添加spuId
            List<SkuDTO> skuDTOS = spuDTO.getSkus();
            //转换为Sku集合
            List<Sku> skus = BeanHelper.copyWithCollection(skuDTOS, Sku.class);
            skus.forEach(sku -> {
                sku.setSpuId(spu.getId());
                sku.setCreateTime(new Date());
                sku.setUpdateTime(new Date());
            });
            //保存操作
            skuMapper.insertList(skus);
        } catch (Exception e) {
            throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
        }
    }

    /**
     * 修改商品上下架
     */
    public void updateSaleable(Long id, Boolean saleable) {
        try {
            //1.更新spu
            Spu spu = new Spu();
            spu.setId(id);
            spu.setSaleable(saleable);
            spuMapper.updateByPrimaryKeySelective(spu);

            String routingKey = saleable ? MQConstants.RoutingKey.ITEM_UP_KEY : MQConstants.RoutingKey.ITEM_DOWN_KEY;
            amqpTemplate.convertAndSend(MQConstants.Exchange.ITEM_EXCHANGE_NAME, routingKey, id);
        } catch (AmqpException e) {
            throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
        }
    }

    /**
     * 根据spuId查询spuDetail信息回显
     *
     * @param id
     * @return
     */
    public SpuDetailDTO querySpuDetailBySpuId(Long id) {
        //spu和s'puDetail共用主键
        SpuDetail spuDetail = spuDetailMapper.selectByPrimaryKey(id);
        if (spuDetail == null) {
            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }
        return BeanHelper.copyProperties(spuDetail, SpuDetailDTO.class);
    }

    /**
     * 根据spuId查询所有sku集合
     *
     * @param id
     * @return
     */
    public List<SkuDTO> querySkusBySpuId(Long id) {
        Example example = new Example(Sku.class);
        example.createCriteria().andEqualTo("spuId", id);
        List<Sku> skus = skuMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(skus)) {
            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }
        return BeanHelper.copyWithCollection(skus, SkuDTO.class);
    }

    /**
     * 修改商品->上下架，更新spu信息，同时需要更新sku
     *
     * @param spuDTO
     */
    public void updateGoods(SpuDTO spuDTO) {
        Long spuId = spuDTO.getId();
        if (spuId == null) {
            //请求参数有误
            throw new LyException(ExceptionEnum.INVALID_PARAM_ERROR);
        }
        //1删除sku
        Sku sku = new Sku();
        sku.setSpuId(spuId);
        //查询数量
        int size = skuMapper.selectCount(sku);
        if (size > 0) {
            //删除
            int count = skuMapper.delete(sku);
            if (size != count) {
                throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
            }
        }
        //2.修改spu
        Spu spu = BeanHelper.copyProperties(spuDTO, Spu.class);
        if (spu == null) {
            throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
        }
        spu.setSaleable(false);
        spu.setCreateTime(new Date());
        spu.setUpdateTime(new Date());
        int count = spuMapper.updateByPrimaryKeySelective(spu);
        if (count != 1) {
            throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
        }
        //3.修改spuDtail
        SpuDetail spuDetail = BeanHelper.copyProperties(spuDTO.getSpuDetail(), SpuDetail.class);
        spuDetail.setSpuId(spu.getId());
        spuDetail.setCreateTime(new Date());
        spuDetail.setUpdateTime(new Date());
        count = spuDetailMapper.updateByPrimaryKeySelective(spuDetail);
        if (count != 1) {
            throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
        }
        //4.添加sku
       /* List<SkuDTO> skuDTOS = spuDTO.getSkus();
        List<Sku> skus = skuDTOS.stream().map(skuDTO -> {
            skuDTO.setEnable(false);
            skuDTO.setSpuId(spu.getId());
            return BeanHelper.copyProperties(skuDTO, Sku.class);
        }).collect(Collectors.toList());*/
        List<Sku> skus = BeanHelper.copyWithCollection(spuDTO.getSkus(), Sku.class);
        skus.forEach(newSku -> {
            newSku.setEnable(false);
            newSku.setSpuId(spu.getId());
            newSku.setCreateTime(new Date());
            newSku.setUpdateTime(new Date());
        });
        count = skuMapper.insertList(skus);
        if (count != skus.size()) {
            throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
        }
    }

    public SpuDTO findSpuById(Long id) {
        Spu spu = spuMapper.selectByPrimaryKey(id);
        if (spu == null) {
            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }
        SpuDTO spuDTO = BeanHelper.copyProperties(spu, SpuDTO.class);
        //给spuDTO对象封装spuDetail
        SpuDetailDTO spuDetailDTO = querySpuDetailBySpuId(spuDTO.getId());
        spuDTO.setSpuDetail(spuDetailDTO);
        //给spuDTO对象封装sku集合
        List<SkuDTO> skuDTOS = querySkusBySpuId(spuDTO.getId());
        spuDTO.setSkus(skuDTOS);
        return spuDTO;
    }

    public List<SkuDTO> findSkusBySkuIds(List<Long> ids) {
        List<Sku> skus = skuMapper.selectByIdList(ids);
        if (CollectionUtils.isEmpty(skus)) {
            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }
        return BeanHelper.copyWithCollection(skus, SkuDTO.class);
    }

    public void minusStock(Map<Long, Integer> mapParam) {
        //循环map中的entry
        mapParam.entrySet().forEach(entry -> {
            Sku record = new Sku();
            record.setId(entry.getKey());
            //得到现有sku中的数据
            Sku sku = skuMapper.selectByPrimaryKey(entry.getKey());
            //将当前的sku库存减去要减少的数量
            record.setStock(sku.getStock()-entry.getValue());
            //更新
            skuMapper.updateByPrimaryKeySelective(record);
        });
    }
}
